/* eslint-disable no-undef */
/**
 * Created by msi on 2017/11/24 0024.
 */
/**
 * Created by hao.cheng on 2017/4/17.
 */

import React from "react";
import {Card, Col, Row, Button, Radio, Switch} from "antd";
import * as d3 from "d3";
import '../../style/odui.less';
import HorizontalTimelineContent from '../timeline/HorizontalTimelineContent';
import GameInfo from './content';
import  d3tip from "d3-tip";
import  Flox from "../../Flox/Flox.js"
import GUI from "../../Flox/GUI.js"
import Model from "../../Flox/FloxModel"
import MapComponent_d3 from "../../Flox/MapComponent_d3"

Flox.GUI = GUI;
Flox.Model = Model;
Flox.MapComponent_d3 = MapComponent_d3;
var margin = {top: 50, right: 50, bottom: 50, left: 50},
    width = 500,
    height = 500;
Flox.initFlox();
var currentHour = 0;
var minvalue = 0, maxvalue = 100;
//定义最小值和最大值对应的颜色
var a = d3.rgb(255, 255, 255);  //浅蓝色
var b = d3.rgb(145, 201, 94);    //蓝色
var allData = null;


//获取数据
function getData(callback) {
    d3.json("ODMatrix2.json", function (miserables) {
        allData = miserables;
        callback(allData)
    });
}

//初始化最大最小值
function countMinMax(miserables) {
    // 将边的值赋予到矩阵中，并计算节点出现的次数
    let temMax = [];
    let temMin = [];
    miserables.links.forEach(function (link) {
        temMax.push(d3.max(link.v))
        temMin.push(d3.min(link.v))
    });
    maxvalue = d3.max(temMax);
    minvalue = d3.min(temMin);
    height = 9 * miserables.nodes.length;
    width = height;
}

//绘制图例
function drawLegend() {

    var width = 1200;
    var svg = d3.select("#svg_legend").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", 40)
        .append("g")
        .attr("transform", "translate(" + 0 + "," + 0 + ")");

    //定义一个线性渐变
    var defs = svg.append("defs");

    var linearGradient = defs.append("linearGradient")
        .attr("id", "linearColor")
        .attr("x1", "0%")
        .attr("y1", "0%")
        .attr("x2", "100%")
        .attr("y2", "0%");

    var stop1 = linearGradient.append("stop")
        .attr("offset", "0%")
        .style("stop-color", a.toString());

    var stop2 = linearGradient.append("stop")
        .attr("offset", "100%")
        .style("stop-color", b.toString());

    //添加一个矩形，并应用线性渐变
    var colorRect = svg.append("rect")
        .attr("x", width / 2)
        .attr("y", 0)
        .attr("width", 140)
        .attr("height", 30)
        .style("fill", "url(#" + linearGradient.attr("id") + ")");

//添加文字
    var minValueText = svg.append("text")
        .attr("class", "valueText")
        .attr("x", width / 2 - 10)
        .attr("y", 30)
        .attr("dy", "-0.5em")
        .text(function () {
            return minvalue;
        });

    var maxValueText = svg.append("text")
        .attr("class", "valueText")
        .attr("x", width / 2 + 140)
        .attr("y", 30)
        .attr("dy", "-0.5em")
        .text(function () {
            return maxvalue;
        });

}


//刷新svg 数据
function reFreshData(hour, isOne) {
    //清空上一次绘制的结果
    if (isOne) {
        document.getElementById("svg").innerHTML = "";
    } else {
    }


//定义一个线性比例尺，将最小值和最大值之间的值映射到[0, 1]
    var linear = d3.scale.linear()
        .domain([minvalue, maxvalue])
        .range([0, 1]);


//颜色插值函数
    var computeColor = d3.interpolate(a, b);

    var x = d3.scale.ordinal().rangeBands([0, height]),//离散的映射  x就已经算好了区间格网的大小了
        z = d3.scale.linear().domain([minvalue, maxvalue]).clamp(true),//定义域  找到数据中的最大值和最小值
        c = d3.scale.category10().domain(d3.range(10));//10种颜色值

    var svg = d3.select("#svg").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .style("margin-left", margin.left + "px")
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var miserables = allData;

    var matrix = [],
        nodes = miserables.nodes,
        n = nodes.length;

    // 初始化矩阵值
    nodes.forEach(function (node, i) {
        node.index = i;
        node.count = 0;
        matrix[i] = d3.range(n).map(function (j) {
            return {x: j, y: i, z: 0};
        });
    });

    // 将边的值赋予到矩阵中，并计算节点出现的次数
    miserables.links.forEach(function (link) {
        matrix[link.o - 1][link.d - 1].z += link.v[hour];
        // matrix[link.target][link.source].z += link.value;
        nodes[link.o - 1].count += link.v[hour];
        nodes[link.d - 1].count += link.v[hour];
    });

    console.log(nodes);

    // 初始化排序方式
    var orders = {
        //按名字排序
        name: d3.range(n).sort(function (a, b) {
            return d3.ascending(nodes[a].name, nodes[b].name);
        }),
        //按照节点出现的次数
        count: d3.range(n).sort(function (a, b) {
            return nodes[b].count - nodes[a].count;
        }),
        //按分组排序
        group: d3.range(n).sort(function (a, b) {
            return d3.ascending(nodes[b].group[0], nodes[a].group[0]);
        })
    };

    // 默认按照名字排序
    //设置定义域 以及值域
    // x.domain(orders.name);
    x.domain(orders.group);
    // x.domain(orders.count);
    //绘制画布
    svg.append("rect")
        .attr("class", "background")
        .attr("width", height)
        .attr("height", height);

    var row = svg.selectAll(".row")
        .data(matrix)
        .enter().append("g")
        .attr("class", "row")
        .attr("transform", function (d, i) {
            return "translate(0," + x(i) + ")";
        })
        .each(row);

    row.append("line")
        .attr("x2", height);//画一条0到width的直线


    //放文字
    row.append("text")
        .attr("x", -6)
        .attr("y", x.rangeBand() / 2)
        .attr("dy", ".32em")
        .attr("text-anchor", "end")
        .text(function (d, i) {
            return nodes[i].name;
        });

    var column = svg.selectAll(".column")
        .data(matrix)
        .enter().append("g")
        .attr("class", "column")
        .attr("transform", function (d, i) {
            return "translate(" + x(i) + ")rotate(-90)";
        });

    column.append("line")
        .attr("x1", -height);


    column.append("text")
        .attr("x", 6)
        .attr("y", x.rangeBand() / 2)
        .attr("dy", ".32em")
        .attr("text-anchor", "start")
        .text(function (d, i) {
            return nodes[i].name;
        });


    //添加底部文字
    var buttomText = svg.append("text")
        .attr("class", "valueText")
        .attr("x", width / 2 - 30)
        .attr("y", height + 30)
        .attr("dy", "-0.5em")
        .text(function () {
            return currentHour + "时 OD矩阵";
        });

    function row(row) {
        var cell = d3.select(this).selectAll(".cell")
            .data(row.filter(function (d) {
                return d.z;
            }))
            .enter().append("rect")
            .attr("class", "cell")
            .attr("x", function (d) {
                return x(d.x);
            })
            .attr("width", x.rangeBand())
            .attr("height", x.rangeBand())
            // .style("fill", function (d) {
            //     var t = linear(d.z);
            //     var color = computeColor(t);
            //     return color.toString();
            // })
            .style("fill-opacity", function (d) {
                return z(d.z);
            })
            .style("fill", function (d) {
                var t = linear(d.z);
                var color = computeColor(t);
                return nodes[d.x].group[0] == nodes[d.y].group[0] ? c(nodes[d.x].group[0]) : color.toString();
            })
            .on("mouseover", mouseover)
            .on("mouseout", mouseout).on("click", function (p) {
                //1.绘制当前区域到区域的24小时的OD曲线图
                //2.切换数据时的变化
                //3.能否画一个框来表达区域内外
                let oNode = miserables.nodes[p.x];
                let dNode = miserables.nodes[p.y];
                let vArray = miserables.links.filter((t) => {
                    return t.o == p.x + 1 && t.d == p.y + 1
                })[0];
                let lineData = [];
                let title = oNode.name + "——>" + dNode.name
                for (let i = 0; i < 24; i++) {
                    lineData.push({
                        "时刻": i,
                        "OD量": vArray.v[i]
                    })
                }
                // drawLineChart(lineData, title);
                // initMap();
            });
    }

    function mouseover(p) {
        //就画出当前OD量的曲线图
        d3.selectAll(".row text").classed("active", function (d, i) {
            return i == p.y;
        });
        d3.selectAll(".column text").classed("active", function (d, i) {
            return i == p.x;
        });
    }

    function mouseout() {
        d3.selectAll("text").classed("active", false);
    }

    d3.select("#order").on("change", function () {
        clearTimeout(timeout);
        order(this.value);
    });


    //4.增加切换的一个动画效果
    function order(value) {
        x.domain(orders[value]);

        var t = svg.transition().duration(2500);

        t.selectAll(".row")
            .delay(function (d, i) {
                return x(i) * 4;
            })
            .attr("transform", function (d, i) {
                return "translate(0," + x(i) + ")";
            })
            .selectAll(".cell")
            .delay(function (d) {
                return x(d.x) * 4;
            })
            .attr("x", function (d) {
                return x(d.x);
            });

        t.selectAll(".column")
            .delay(function (d, i) {
                return x(i) * 4;
            })
            .attr("transform", function (d, i) {
                return "translate(" + x(i) + ")rotate(-90)";
            });
    }
}
var timeout = null;

//绘制LineChart
function drawLineChart(data, title) {
    //清空上一次绘制的
    document.getElementById("svg_line").innerHTML = "";
    var svg = dimple.newSvg("#svg_line", 590, 400);

    // Create and Position a Chart
    var myChart = new dimple.chart(svg, data);
    myChart.setBounds(60, 30, 500, 300);
    var x = myChart.addCategoryAxis("x", "时刻")
    myChart.addMeasureAxis("y", "OD量");
    myChart.addColorAxis("OD量", [a, b]);
    var lines = myChart.addSeries(title, dimple.plot.line);
    lines.lineWeight = 2;
    lines.lineMarkers = true;
    myChart.addLegend(0, 0, 500, 50, "right", lines);
    //在pop中显示
    // myChart.legends.pop();
    myChart.draw();


}


var svg;//地图svg对象

var baseMap, arcGroup, points;//地图svg的图层
d3.tip = d3tip;
var zoom = d3.behavior.zoom()
    .scaleExtent([1, 20])
    .on("zoom", zoomer)

//设置地图画布大小
var width_map = 960,
    height_map = 500;
var tooltip = d3.tip()
    .attr('class', 'd3-tip')
    .direction('e')
    .offset([5, 10])
    .html(function (d) {
        return "<span style='color:black'>" + d + "</span>";
    })

//计算线粗细来表达OD量
var lineStroke = d3.scale.sqrt().domain([10, 100]).range([2, 12]);

var projection, path;

//-------------------------------------------------------------
//获得地图的中心
function getCenters(features) {
    var longitudeMin = 100000;
    var latitudeMin = 100000;
    var longitudeMax = 0;
    var latitudeMax = 0;
    features.forEach(function (e) {
        var a = d3.geo.bounds(e);
        if (a[0][0] < longitudeMin) {
            longitudeMin = a[0][0];
        }
        if (a[0][1] < latitudeMin) {
            latitudeMin = a[0][1];
        }
        if (a[1][0] > longitudeMax) {
            longitudeMax = a[1][0];
        }
        if (a[1][1] > latitudeMax) {
            latitudeMax = a[1][1];
        }
    });

    var a = (longitudeMax + longitudeMin) / 2;
    var b = (latitudeMax + latitudeMin) / 2;

    return [a, b];
}

//设置地图的大小
function getZoomScale(features, width, height) {
    var longitudeMin = 100000;
    var latitudeMin = 100000;
    var longitudeMax = 0;
    var latitudeMax = 0;
    features.forEach(function (e) {
        var a = d3.geo.bounds(e);

        if (a[0][0] < longitudeMin) {
            longitudeMin = a[0][0];
        }
        if (a[0][1] < latitudeMin) {
            latitudeMin = a[0][1];
        }
        if (a[1][0] > longitudeMax) {
            longitudeMax = a[1][0];
        }
        if (a[1][1] > latitudeMax) {
            latitudeMax = a[1][1];
        }
    });

    var a = longitudeMax - longitudeMin;
    var b = latitudeMax - latitudeMin;

    return Math.min(width / a, height / b);
}


//设置地图缩放和拖动效果 所有图形同时移动缩放
function zoomer() {
    if (arcGroup) {
        //注意缩放时候线的粗细也要变化
        arcGroup.attr("transform", "translate(" + zoom.translate() + ")scale(" + zoom.scale() + ")")
            .selectAll(".arc").style('stroke-width', function (d) {
            return lineStroke(d.v) / zoom.scale()
        })
    }
    baseMap.attr("transform", "translate(" + zoom.translate() + ")scale(" + zoom.scale() + ")")

    points.attr("transform", "translate(" + zoom.translate() + ")scale(" + zoom.scale() + ")")
        .selectAll("circle")
        .attr("r", function (d) {
            return 5
        })
}


function initMap() {
    document.getElementById("svg_map").innerHTML = "";
    svg = d3.select("#svg_map").append("svg")
        .attr("width", width_map)
        .attr("height", height_map).call(tooltip);


    //加载地图
    d3.json("jiedao_polygon.geojson", function (error, data) {
        var centers = getCenters(data.features);
        var zoomScale = getZoomScale(data.features, width_map, height_map);

        //先定义一个投影
        projection = d3.geo.mercator()
            .center(centers)
            .translate([width_map / 2, height_map / 2])
            .scale(zoomScale * 30);

        //通过投影函数生成地理路径生成器
        path = d3.geo.path().projection(projection);

        baseMap = svg.append("g")
            .attr(function (d) {
                d.dx = 110;
                d.dy = 40;
            })
            .call(zoom);


        var city = baseMap.selectAll("path")
            .data(data.features) //数据
            .enter()
            .append("path").style('stroke', 'white')
            .attr("fill", function (d, i) {
                return "#ccc";
            }).attr("d", path)

            .on("mouseover", function (d, i) {
                d3.select(this).attr("fill", "#000");
            })
            .on("mouseout", function (d, i) {
                d3.select(this).attr("fill", "#ccc");
            });

        drawLinesOver([], {}, path, svg, projection);
    });

}


/**
 *
 * @param data 数组可以一对多的
 * @param base 一个点就好
 * @param path project的路径
 * @param svg 绘图对象
 * @param projection 投影
 */
function drawLinesOver(data, base, path, svg, projection) {

    //定义一个箭头
    var defs = svg.append("defs");
    var marker = defs.append("marker")
        .attr("id", "marker")
        .attr("markerUnits", "strokeWidth")
        .attr("markerWidth", "12")
        .attr("markerHeight", "12")
        .attr("viewBox", "0 0 12 12")
        .attr("refX", "6")
        .attr("refY", "6")
        .attr("orient", "auto");
    marker.append("path")
        .attr("d", "M2,2 L10,6 L2,10 L6,6 L2,2")
        .attr("style", "fill: #000000;");

    points = svg.append("g");
    // --- 创建补间动画
    var lineTransition = function lineTransition(path) {
        path.transition()
            .duration(1000)
            .attrTween("stroke-dasharray", tweenDash)
            .each("end", function (d, i) {
                //绘制箭头
                path.attr("marker-end", "url(#" + marker.attr("id") + ")");
                //绘制坐标点
                points.selectAll("circle").data(d.coordinates).enter().append("circle").attr("cx", function (d) {
                    return projection(d)[0];
                }).attr("cy", function (d) {
                    return projection(d)[1];
                }).attr("r", 5).attr("fill", "#256").attr("stroke", "#256").attr("opacity", 0.5).on("mouseover", function (d) {
                        tooltip.show(d, this)
                    }
                ).on("mouseout", tooltip.hide)
            });
    };

    var tweenDash = function tweenDash() {
        var len = this.getTotalLength(),
            interpolate = d3.interpolateString("0," + len, len + "," + len);
        return function (t) {
            return interpolate(t);
        };
    };
    //终点
    base = {"lat": 0.289, "long": 110.5, "v": 10}
    data = [{
        "lat": 0.375, "long": 110.8, "v": 10
    }]
    var links = [];
    for (var i = 0, len = data.length; i < len; i++) {
        // (note: loop until length - 1 since we're getting the next
        //  item with i+1)
        links.push({
            type: "LineString",
            coordinates: [
                [data[i].long, data[i].lat],
                [base.long, base.lat]
            ],
            v: data[i].v
        });
    }
    arcGroup = svg.append("g");
    var pathArcs = arcGroup.selectAll("arc").data(links);

    //enter
    var xPosition

    //enter
    pathArcs.enter()
        .append("path").style({
        fill: 'none',
    })
        .attr("d", function (d) {
            var t = 0
            var s = 1
            var dx = projection(d.coordinates[t])[0] - projection(d.coordinates[s])[0],
                dy = projection(d.coordinates[t])[1] - projection(d.coordinates[s])[1],
                dr = Math.sqrt(dx * dx + dy * dy);

            var left = projection(d.coordinates[t])[0] < projection(d.coordinates[s])[0] ? true : false
            var sweep = left == true ? 1 : 0


            xPosition = projection(d.coordinates[t])[0]
            return "M" +
                projection(d.coordinates[0])[0] + "," +
                projection(d.coordinates[0])[1] + "A" +
                dr + "," + dr + " 0 0," + sweep + " " +
                projection(d.coordinates[1])[0] + "," +
                projection(d.coordinates[1])[1]
        })
        // .attr("marker-start", "url(#" + marker.attr("id") + ")")
        // .attr("marker-mid", "url(#" + marker.attr("id") + ")")
        // .attr("marker-end", "url(#" + marker.attr("id") + ")")
        .style("stroke", "black")
        .style('stroke-width', function (d) {
            return lineStroke(d.v)
        }).call(lineTransition);
}


class ODMatrix extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            currentHour: currentHour,
            checked: false,
            type: "one"
        }
    }

    startFlow() {
        //定时切换
        var that = this;
        timeout = setInterval(function () {
            currentHour++;
            if (currentHour < 24) {
                that.setState({
                    currentHour: currentHour
                })
                reFreshData(currentHour, that.state.type == "one");
            } else {
                currentHour = 0;
                that.setState({
                    currentHour: currentHour,
                    checked: false
                })
                reFreshData(currentHour, that.state.type == "one");
                that.clearFolw.bind(that)();
            }

        }, 500);
    }

    clearFolw() {
        window.clearInterval(timeout);
    }

    componentDidMount() {
        var that = this;
        getData(function (allData) {
            countMinMax(allData);
            drawLegend();
            reFreshData(currentHour, that.state.type == "one");
        });
    }

    handleTypeChange(e) {
        this.setState({
            type: e.target.value
        })
        const type = e.target.value;
        switch (type) {
            case "one":
                reFreshData(this.state.currentHour, true);
                break
                    ;
            case "many":
                //先清空
                document.getElementById("svg").innerHTML = "";
                reFreshData(this.state.currentHour, false)
                ;
                break
                    ;
            case "clear":

                ;
                break
                    ;
        }
        console.log(e.target.value);
    }

    onStartChange(checked) {
        console.log(checked);
        this.setState({
            checked: checked
        })
        if (checked) {
            this.startFlow.bind(this)();
        } else {
            this.clearFolw.bind(this)();
        }
    }

    render() {
        const that = this;
        this.data = GameInfo.map((game, index) => {
            return ({
                date: game.date,
                component: (
                    <div className="container" key={index}>
                        <h1>{ `The Elder Scrolls ${index + 1}:`}</h1>
                        <h2>{ game.subtitle }</h2>
                        <hr />
                        <p>{ game.content}</p>
                        <hr />
                    </div>
                )
            });
        });
        return (
            <div className="gutter-example">
                <Row gutter={100}>
                    <Col className="gutter-row" md={24}>
                        <div className="gutter-box">
                            <HorizontalTimelineContent
                                content={this.data} updateIndex={ this.state.currentHour } onItemClick={(index) => {
                                console.log(index);
                                currentHour = index;
                                that.setState({
                                    currentHour: currentHour
                                });
                                reFreshData(index, that.state.type == "one");
                            }
                            }
                            />
                            <Card title="OD矩阵图" bordered={false}>
                                {/*<EchartsArea />*/}
                                <Radio.Group value={this.state.type} onChange={this.handleTypeChange.bind(that)}>
                                    <Radio.Button value="one">单个查看</Radio.Button>
                                    <Radio.Button value="many">并列添加</Radio.Button>
                                </Radio.Group>
                                <Button style={{margin: 10}} onClick={() => {
                                    document.getElementById("svg").innerHTML = "";
                                    document.getElementById("svg_line").innerHTML = "";
                                    document.getElementById("svg_map").innerHTML = "";
                                }}
                                >清除</Button>

                                < Row gutter={4} type="flex" justify="end">
                                    <Col span={2}>
                                        播放:<Switch
                                        checkedChildren="开"
                                        unCheckedChildren="关"
                                        checked={this.state.checked}
                                        onChange={this.onStartChange.bind(that)}
                                    />
                                    </Col>
                                    <Col span={2}>
                                        排序:<Switch
                                        checkedChildren="行政区"
                                        unCheckedChildren="OD流入" onChange={
                                            function () {
                                                // countyClick();
                                            }
                                    }/>
                                    </Col>
                                </Row>

                                <div id="svg_legend"/>
                                <div id="svg_line"/>
                                <div id="svg_map"/>
                                <div id="svg"/>
                            </Card>
                        </div>
                    </Col>
                </Row>
            </div>
        )
    }
}

export default ODMatrix;